﻿using System;
using System.Drawing;
using System.Linq;
using NewMixedMode;
using Styx;
using Styx.CommonBot;
using Styx.WoWInternals.DBC;

namespace TheFinalCall
{

    #region Nested type: WoWContextEventArg

    public class WoWContextEventArg : EventArgs
    {
        public readonly WoWContext CurrentContext;
        public readonly WoWContext PreviousContext;

        public WoWContextEventArg(WoWContext currentContext, WoWContext prevContext)
        {
            CurrentContext = currentContext;
            PreviousContext = prevContext;
        }
    }

    #endregion

    partial class TheFinalCallRoutine
    {
        private static WoWContext _lastContext;
        private bool _contextEventSubscribed;

        internal static bool IsQuesting { get; set; }

        internal static WoWContext CurrentWoWContext
        {
            get
            {
                if (!StyxWoW.IsInGame)
                    return WoWContext.None;

                Map map = StyxWoW.Me.CurrentMap;

                if (map.IsBattleground || map.IsArena)
                {
                    return WoWContext.Battlegrounds;
                }

                if (map.IsDungeon)
                {
                    return WoWContext.Instances;
                }

                if (Me.IsInGroup())
                {
                    // return TheFinalCallSettings.Instance.WorldGroupBehaviors;
                    return WoWContext.Instances;
                }

                // return TheFinalCallSettings.Instance.WorldSoloBehaviors;
                return WoWContext.Normal;
            }
        }

        public static event EventHandler<WoWContextEventArg> OnWoWContextChanged;

        private void UpdateContext()
        {
            // Subscribe to the map change event, so we can automatically update the context.
            if (!_contextEventSubscribed)
            {
                // Subscribe to OnBattlegroundEntered. Just 'cause.
                BotEvents.Battleground.OnBattlegroundEntered += e => UpdateContext();
                _contextEventSubscribed = true;
            }

            IsQuesting = IsBotInUse("Quest");

            WoWContext current = CurrentWoWContext;

            // Can't update the context when it doesn't exist.
            if (current == WoWContext.None)
                return;


            if (current != _lastContext && OnWoWContextChanged != null)
            {
                DescribeContext();
                try
                {
                    OnWoWContextChanged(this, new WoWContextEventArg(current, _lastContext));
                }
                catch
                {
                    // Eat any exceptions thrown.
                }
                _lastContext = current;
            }
        }

        public static void DescribeContext()
        {
            string sRace = Me.Race.ToString().CamelToSpaced();
            if (Me.Race == WoWRace.Pandaren)
                sRace = " " + Me.FactionGroup.ToString() + sRace;

            Logger.Write(Color.LightGreen, "Your Level {0}{1} {2} {3} Build is", Me.Level, sRace, SpecializationName(),
                         Me.Class.ToString());

            string sRunningAs = "";

            if (Me.CurrentMap == null)
                sRunningAs = "Solo";
            else
            {
                if (Me.CurrentMap.IsArena)
                    sRunningAs = " Arena ";
                else if (Me.CurrentMap.IsBattleground)
                    sRunningAs = " Battleground ";
                else if (Me.CurrentMap.IsScenario)
                    sRunningAs = " Scenario ";
                else if (Me.CurrentMap.IsDungeon)
                    sRunningAs = " Dungeon ";
                else if (Me.CurrentMap.IsRaid)
                    sRunningAs = " Raid ";
                else if (Me.CurrentMap.IsInstance)
                    sRunningAs = " Instance ";

                if (!Me.IsInGroup())
                    sRunningAs = "Solo " + sRunningAs;
                else
                    sRunningAs = string.Format("{0}m {1}",
                                               (int) Math.Max(Me.CurrentMap.MaxPlayers, Me.GroupInfo.GroupSize),
                                               sRunningAs);
            }

            Logger.Write(Color.LightGreen, "... running the {0} bot {1}in {2}",
                         GetBotName(),
                         sRunningAs,
                         Me.RealZoneText
                );

            Item.WriteCharacterGearAndSetupInfo();

            if (Targeting.PullDistance < 25)
                Logger.Write(Color.White, "your Pull Distance is {0:F0} yds which is low for any class!!!",
                             Targeting.PullDistance);
        }

        private static string SpecializationName()
        {
            if (Me.Specialization == WoWSpec.None)
                return "Lowbie";

            string spec = Me.Specialization.ToString().CamelToSpaced();
            int idxLastSpace = spec.LastIndexOf(' ');
            if (idxLastSpace >= 0 && ++idxLastSpace < spec.Length)
                spec = spec.Substring(idxLastSpace);

            return spec;
        }

        public static string GetBotName()
        {
            BotBase bot = null;

            if (TreeRoot.Current != null)
            {
                if (!(TreeRoot.Current is MixedModeEx))
                    bot = TreeRoot.Current;
                else
                {
                    var mmb = (MixedModeEx) TreeRoot.Current;
                    if (mmb != null)
                    {
                        if (mmb.SecondaryBot.RequirementsMet)
                            return mmb.SecondaryBot != null
                                       ? "Mixed:" + mmb.SecondaryBot.Name
                                       : "Mixed:[secondary null]";
                        return mmb.PrimaryBot != null ? "Mixed:" + mmb.PrimaryBot.Name : "Mixed:[primary null]";
                    }
                }
            }

            return bot.Name;
        }

        public static bool IsBotInUse(params string[] nameSubstrings)
        {
            string botName = GetBotName().ToUpper();
            return nameSubstrings.Any(s => botName.Contains(s.ToUpper()));
        }
    }
}